//Shkolnij Rostislav
package CalculationCore;

public class CCPURegister {
	private double dFullNumber;
	private double dMantissa;
	private int iExponenta[] = {0, 0, 0}; 
	private int iIntDigitsEntered, iPartDigitsEntered; 
	private boolean hasCommaSign, hasExponenta;
	
	// panel input:  123.6320 E 8
	// normed float: 1.23632 E 10
	// float: 		 12363200000 
	// iMantissa = 123.6320,  iExponenta = {0 , 8}
	// iIntDigitsEntered = 3, iPartDigitsEntered = 4, hasCommaSign = true; 
	
	public CCPURegister()	{
		cleanup();
	}
	
	public CCPURegister(int src)	{
		dFullNumber =  (double) src;
		this.refreshdMantAndExp();
	}
	
	public CCPURegister(double src)	{
		dFullNumber = src;
		this.refreshdMantAndExp();
	}
	
	public CCPURegister(CCPURegister src)	{
		copy(src);
	}
	
	public void cleanup()
	{
		setdFullNumber(0.0);
		setdMantissa(0.0);
		setiExponenta(0, 0, 0);
		setiIntDigitsEntered(0);
		setiPartDigitsEntered(0);
		setHasCommaSign(false);
		setHasExponenta(false);
	}
	
	public void cleanupExponenta()
	{
		setiExponenta(0, 0, 0);
		refreshdFullNumber();
	}
	
	public void copy(CCPURegister src)	{
		dFullNumber = src.getdFullNumber();
		dMantissa = src.getdMantissa();
		iExponenta = src.getiExponenta().clone();
		iIntDigitsEntered = src.getiIntDigitsEntered();
		iPartDigitsEntered = src.getiPartDigitsEntered();
		hasCommaSign = src.getHasCommaSign();
		hasExponenta = src.getHasExponenta();
	}
	
	public void insertDigitInMantissa(int digit)	{
		if(iIntDigitsEntered + iPartDigitsEntered < 8)
		{
			if(getHasCommaSign() == false)
			{
				if(dMantissa == 0.0) 
					iIntDigitsEntered = 0;
				dMantissa = dMantissa*10 + (double)digit;
				if(dMantissa == 0.0) 
					iIntDigitsEntered = 1;
				else
					iIntDigitsEntered++;
			}
			else 
			{
				iPartDigitsEntered++;
				dMantissa = dMantissa + (((double)digit)/Math.pow(10, getiPartDigitsEntered()));
			}
		}
		refreshdFullNumber();
	}
	
	public void insertMinusInMantissa()	{
		dMantissa = -dMantissa;
		refreshdFullNumber();
	}
	
	public void insertDigitInExponenta(int digit)	{
		this.iExponenta[1] = this.iExponenta[0];
		this.iExponenta[0] = digit;
		refreshdFullNumber();
	}
	
	public void insertMinusInExponenta()	{
		if(iExponenta[2] == 0) iExponenta[2] = 1;
		else iExponenta[2] = 0;

		refreshdFullNumber();
	}
	
	public void insertComma()	{
		if(iIntDigitsEntered>=0 && iIntDigitsEntered<=8)
			hasCommaSign = true;
	}
	
	public void insertExponenta()	{
		hasExponenta = true;
	}
	
	private void refreshdFullNumber()
	{
		double power = iExponenta[0] + 10*iExponenta[1]; 
		if(iExponenta[2] == 1) 
			power = -power;
		dFullNumber = dMantissa*Math.pow(10, power);
	}
	
	private void refreshdMantAndExp() // 
	{
		if(dFullNumber != 0)
		{
			int mant = (int) Math.floor(Math.log10(dFullNumber)); 
			iExponenta[0] = Math.abs(mant) % 10;
			iExponenta[1] = Math.abs(mant) - Math.abs(mant) % 10;
			iExponenta[2] = (mant >= 0)? 0 : 1;
			dMantissa = dFullNumber / Math.pow(10, mant); 
			
			iIntDigitsEntered = 1; 
			iPartDigitsEntered = 7; //?
			hasCommaSign = true;
		}
		else
		{
			iExponenta[0] = 0;
			iExponenta[1] = 0;
			iExponenta[2] = 0;
			dMantissa = 0.0;  
			iIntDigitsEntered = 1; 
			iPartDigitsEntered = 0;
			hasCommaSign = false;
		}		
			
	}
	
	public void systemOutput()
	{
		//System.out.println(String.format("%+8.8E    mant = %.7f   exp = %d_%d%d   dignum = %d  prtnum = %d  hasC = %b hasE = %b", 
		//		dFullNumber , dMantissa, iExponenta[2], iExponenta[1], iExponenta[0], iIntDigitsEntered, iPartDigitsEntered, hasCommaSign, hasExponenta));
		System.out.println(String.format("%+8.8E    mant = %.7f   exp = %d_%d%d", 
				dFullNumber , dMantissa, iExponenta[2], iExponenta[1], iExponenta[0]));
	}
	
	public String reformToLEDView(boolean normedMode)
	{
		int iexp = iExponenta[1]*10 + iExponenta[0];  
		
		double ret = dMantissa*Math.pow(10, iexp);
		double dpart = Math.abs(ret) - Math.floor(Math.abs(ret) + 0.0000000001);
	
		if (normedMode) {
			if(dMantissa != 0.0){
				if(dpart == 0.0  &&	Math.floor(Math.log10(ret)) + 1 <= 8)
					return String.format("%+d.", (int)ret);
				else
					return String.format("%+1.7E", dFullNumber);
			}
			else
				return String.format("+0.");
		}
		else //mantissa chars to return string
		{
			String s_mnt = "";
			if(dMantissa != 0.0 || hasCommaSign)
			{
				s_mnt = (dMantissa < 0) ? "-" : "+";
				s_mnt += Integer.toString((int) Math.floor(Math.abs(dMantissa)));
				s_mnt += ".";
				if(hasCommaSign)
				{				
					//int inum = (iIntDigitsEntered + iPartDigitsEntered <= 8) ? iPartDigitsEntered : 8 - iIntDigitsEntered;
					if(iPartDigitsEntered != 0)
					{
						dpart = Math.abs(dMantissa) - 
								Math.floor(Math.abs(dMantissa) + 0.0000000001);
						int idig;
						for(int i=0; i<iPartDigitsEntered; i++)
						{
							idig = (int)(Math.round(dpart*Math.pow(10, i+1)))%10;
							s_mnt += Integer.toString(idig);
						}
					} 
				}
			}
			else
			{
				s_mnt = "+0.";
			}
			
			String s_exp = ""; //exponenta chars to return string
			if(hasExponenta)
				s_exp ="E" + 
					(iExponenta[2] == 0 ? "+" : "-" ) + 
					Integer.toString(iExponenta[1]) +
					Integer.toString(iExponenta[0]);
	
			return s_mnt + s_exp;
		}
	}
	
	public boolean checkOutOfPrecisionLimits()
	{
		if( Math.abs(dFullNumber) < 1.0*Math.pow(10.0, -99.0))
		{
			dFullNumber = 0.0;
			this.refreshdMantAndExp();
			//return true;
			return false;
		}
		else if(Math.abs(dFullNumber) > 9.9999999*Math.pow(10, +99.0))
		{
			dFullNumber = 0.0;
			this.refreshdMantAndExp();
			return true;
		}
		else
			return false;
	}
	
	public int getAddress()
	{
		int res;
		res = (int) dFullNumber;
		return res;
	}
	
	//setters & getters-------------------------------
	public double getdMantissa() { 
		return dMantissa;
	}

	public void setdMantissa(double dMantissa) {
		this.dMantissa = dMantissa;
		refreshdFullNumber();
	}

	public int[] getiExponenta() {
		int res[] = {iExponenta[0], iExponenta[1], iExponenta[2]};
		return res;
	}

	public void setiExponenta(int n0, int n1, int n2) {
		this.iExponenta[0] = n0;
		this.iExponenta[1] = n1;
		this.iExponenta[2] = n2;
    }
	
	public int getiIntDigitsEntered() {
		return iIntDigitsEntered;
	}

	public void setiIntDigitsEntered(int iIntDigitsEntered) {
		this.iIntDigitsEntered = iIntDigitsEntered;
	}

	public int getiPartDigitsEntered() {
		return iPartDigitsEntered;
	}

	public void setiPartDigitsEntered(int iPartDigitsEntered) {
		this.iPartDigitsEntered = iPartDigitsEntered;
	}

	public boolean getHasCommaSign() {
		return hasCommaSign;
	}

	public void setHasCommaSign(boolean hasCommaSign) {
		this.hasCommaSign = hasCommaSign;
	}

	public double getdFullNumber() {
		return dFullNumber;
	}

	public void setdFullNumber(double dFullNumber) {
		this.dFullNumber = dFullNumber;
		refreshdMantAndExp();
	}

	public boolean getHasExponenta() {
		return hasExponenta;
	}

	public void setHasExponenta(boolean hasExponenta) {
		this.hasExponenta = hasExponenta;
	}
	
	public boolean isTheSameValue(double src, double rounding) {
		if(Math.abs(this.dFullNumber - src) <= rounding)
			return true;
		else
			return false;
	}
}
